Load data

# Restore the object
Diet_Data_Clean = readRDS(file = "~/Dropbox (Edison_Lab@UGA)/Projects/vet/Deanna/Golden_Data/CleanData.rds")

Frequency at which participants switch categorization

library(dplyr)
library(markovchain)

data <- Diet_Data_Clean[order(Diet_Data_Clean$id, Diet_Data_Clean$calendaryear),]

 # Create a list of all unique categories
all_categories <- unique(data$process.category)

# Creating sequences
data_sequence <- data %>%
  group_by(id) %>%
  summarise(Category_Sequence = list(process.category)) %>%
  ungroup()


# Function to fit Markov chain and return a complete transition matrix
get_complete_matrix <- function(sequence) {
  # Fit the Markov chain
  mcFit <- markovchainFit(data = sequence)$estimate
  # Create a complete matrix including all categories
  complete_matrix <- matrix(0, length(all_categories), length(all_categories),
                            dimnames = list(all_categories, all_categories))
  transitions <- mcFit@transitionMatrix
  # Fill the complete matrix with existing transitions
  rownames_to_use <- intersect(rownames(transitions), all_categories)
  colnames_to_use <- intersect(colnames(transitions), all_categories)
  complete_matrix[rownames_to_use, colnames_to_use] <- transitions[rownames_to_use, colnames_to_use]
  return(complete_matrix)
}

# Adjust the function to convert sequences to transition matrix
get_transition_matrix <- function(sequence_list) {
  mcList <- lapply(sequence_list, get_complete_matrix)
  
  # Summing all matrices
  matrix_sum <- Reduce("+", mcList)
  return(matrix_sum / length(mcList))  # Normalizing
}

# Creating the transition matrix
transition_matrix <- get_transition_matrix(data_sequence$Category_Sequence)
print(transition_matrix)
                    Ultra Processed Minimally Processed    Processed          UNK          N/A TBD
Ultra Processed        0.8564600150        0.0199166197 0.0159196859 0.0011005256 0.0001642576   0
Minimally Processed    0.0336164821        0.0502041487 0.0061377573 0.0003832676 0.0000000000   0
Processed              0.0357314936        0.0099649584 0.0177069645 0.0009855453 0.0000000000   0
UNK                    0.0022996058        0.0003285151 0.0006570302 0.0003285151 0.0000000000   0
N/A                    0.0003285151        0.0000000000 0.0000000000 0.0000000000 0.0000000000   0
TBD                    0.0003285151        0.0000000000 0.0000000000 0.0000000000 0.0000000000   0
library(ggplot2)

transition_df <- as.data.frame(as.table(transition_matrix))
colnames(transition_df) <- c("From", "To", "Frequency")

heatmap1 = ggplot(transition_df, aes(x = From, y = To, fill = Frequency)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0.5) +
  theme_minimal() +
  labs(title = "Transition Heatmap", x = "From Category", y = "To Category", fill = "Transition Frequency")

implies a significant tendency for subjects to remain in the last category listed. This can indicate that once subjects enter this category, they are likely to stay there, suggesting stability or a terminal stage depending on the context of the study.

# Assuming 'data' is your dataframe and 'CalendarYear' is the column with the year as character
data$Year <- as.integer(data$calendaryear)

# Calculate the duration of stay in each category for each subject
durations <- data %>%
  group_by(id, process.category) %>%
  summarise(
    Start_Year = min(Year),
    End_Year = max(Year),
    Duration = End_Year - Start_Year + 1  # +1 because if start and end year are the same, duration is 1 year
  ) %>%
  ungroup()
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
# View the first few rows of the durations data frame
head(durations)

# Calculate the average duration of stay per category
average_durations <- durations %>%
  group_by(process.category) %>%
  summarise(Average_Duration = mean(Duration))

# View the average durations
head(average_durations)


durations_datatable = datatable(durations, options = list(), class = "display")
durations_datatable

average_durations_datatable = datatable(average_durations, options = list(), class = "display")
average_durations_datatable
# Adding a small constant to handle zeros
k = 0.001
transition_df$Freq_Adjusted = transition_df$Freq + k
# Applying a log transformation (base 10)
transition_df$Log_Frequency = log10(transition_df$Freq_Adjusted)
# Converting matrix to data frame for plotting
#transition_df <- as.data.frame(as.table(transition_matrix))

# Create interactive heatmap
heatmap2 = plot_ly(data = transition_df, x = ~From, y = ~To, z = ~Log_Frequency, type = "heatmap", colors = colorRamp(c("blue", "white", "red")),
        text = ~paste("Transition from", From, "to", To, "<br>Probability:", Frequency),
        hoverinfo = "text") %>%
  layout(title = "Transition Matrix Heatmap",
         xaxis = list(title = "From Category"),
         yaxis = list(title = "To Category", autorange = "reversed"))  # Reversing y-axis to match heatmap conventions
heatmap2

Frequency for switching diet companies


 # Create a list of all unique categories
all_categories <- unique(data$Parent_Company)

# Function to fit Markov chain and return a complete transition matrix
get_complete_matrix <- function(sequence) {
  # Fit the Markov chain
  mcFit <- markovchainFit(data = sequence)$estimate
  # Create a complete matrix including all categories
  complete_matrix <- matrix(0, length(all_categories), length(all_categories),
                            dimnames = list(all_categories, all_categories))
  transitions <- mcFit@transitionMatrix
  # Fill the complete matrix with existing transitions
  rownames_to_use <- intersect(rownames(transitions), all_categories)
  colnames_to_use <- intersect(colnames(transitions), all_categories)
  complete_matrix[rownames_to_use, colnames_to_use] <- transitions[rownames_to_use, colnames_to_use]
  return(complete_matrix)
}

# Adjust the function to convert sequences to transition matrix
get_transition_matrix <- function(sequence_list) {
  mcList <- lapply(sequence_list, get_complete_matrix)
  
  # Summing all matrices
  matrix_sum <- Reduce("+", mcList)
  return(matrix_sum / length(mcList))  # Normalizing
}

# Creating the transition matrix
transition_matrix <- get_transition_matrix(data_sequence$Category_Sequence)
# Assuming 'data' is your dataframe and 'CalendarYear' is the column with the year as character
data$Year <- as.integer(data$calendaryear)

# Calculate the duration of stay in each category for each subject
durations <- data %>%
  group_by(id, Parent_Company) %>%
  summarise(
    Start_Year = min(Year),
    End_Year = max(Year),
    Duration = End_Year - Start_Year + 1  # +1 because if start and end year are the same, duration is 1 year
  ) %>%
  ungroup()
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
# View the first few rows of the durations data frame
head(durations)

# Calculate the average duration of stay per category
average_durations <- durations %>%
  group_by(Parent_Company) %>%
  summarise(Average_Duration = mean(Duration))

# View the average durations
head(average_durations)


durations_datatable2 = datatable(durations, options = list(), class = "display")
durations_datatable

average_durations_datatable2 = datatable(average_durations, options = list(), class = "display")
average_durations_datatable

Frequency for switching diet brands


 # Create a list of all unique categories
all_categories <- unique(data$Brand_Company)

# Function to fit Markov chain and return a complete transition matrix
get_complete_matrix <- function(sequence) {
  # Fit the Markov chain
  mcFit <- markovchainFit(data = sequence)$estimate
  # Create a complete matrix including all categories
  complete_matrix <- matrix(0, length(all_categories), length(all_categories),
                            dimnames = list(all_categories, all_categories))
  transitions <- mcFit@transitionMatrix
  # Fill the complete matrix with existing transitions
  rownames_to_use <- intersect(rownames(transitions), all_categories)
  colnames_to_use <- intersect(colnames(transitions), all_categories)
  complete_matrix[rownames_to_use, colnames_to_use] <- transitions[rownames_to_use, colnames_to_use]
  return(complete_matrix)
}

# Adjust the function to convert sequences to transition matrix
get_transition_matrix <- function(sequence_list) {
  mcList <- lapply(sequence_list, get_complete_matrix)
  
  # Summing all matrices
  matrix_sum <- Reduce("+", mcList)
  return(matrix_sum / length(mcList))  # Normalizing
}

# Creating the transition matrix
transition_matrix <- get_transition_matrix(data_sequence$Category_Sequence)
# 
data$Year <- as.integer(data$calendaryear)

# Calculate the duration of stay in each category for each subject
durations <- data %>%
  group_by(id, Brand_Company) %>%
  summarise(
    Start_Year = min(Year),
    End_Year = max(Year),
    Duration = End_Year - Start_Year + 1  # +1 because if start and end year are the same, duration is 1 year
  ) %>%
  ungroup()
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
# View the first few rows of the durations data frame
head(durations)

# Calculate the average duration of stay per category
average_durations <- durations %>%
  group_by(Brand_Company) %>%
  summarise(Average_Duration = mean(Duration))

# View the average durations
head(average_durations)


durations_datatable3 = datatable(durations, options = list(), class = "display")
durations_datatable3

average_durations_datatable3 = datatable(average_durations, options = list(), class = "display")
average_durations_datatable3
save(heatmap2, file = "~/Dropbox (Edison_Lab@UGA)/Projects/vet/Deanna/Golden_Data/figures_trends.RData")

save(average_durations_datatable,durations_datatable,durations_datatable2,average_durations_datatable2,average_durations_datatable3,durations_datatable3, file = "~/Dropbox (Edison_Lab@UGA)/Projects/vet/Deanna/Golden_Data/tables_trends.RData")

Death data and diet data

# Merge the datasets
combined_data <- left_join(death_data, Diet_Data_Clean, by = c("id", "study_year"))
# Logistic regression to see if diet predicts disease occurrence
model_disease <- glm(condition != "No Disease" ~ BCS + Brand_Company + Parent_Company + process.category + process.subtype, 
                     data = combined_data, family = "binomial")

# Logistic regression to see if diet predicts death caused by disease
model_death <- glm(condition != "No Disease" & is_cause_of_death == 1 ~ BCS + Brand_Company + Parent_Company + process.category + process.subtype, 
                   data = combined_data, family = "binomial")

# Summarize the model
summary(model_disease)
summary(model_death)
# Calculate frequencies
condition_frequency <- combined_data %>%
  group_by(process.category, condition)%>%
  filter(!is.na(process.category)) %>%
  summarize(frequency = n(), .groups = 'drop')
condition_frequency

# Plot the frequency of diseases by process category
disease_plot <-ggplot(condition_frequency, aes(x = condition, y = frequency, fill = process.category)) +
  geom_bar(stat = "identity", position = "stack") +  # 'stack' stacks the bars for different conditions
  labs(title = "Frequency of Diseases by Process Category",
       x = "Process Category",
       y = "Frequency of Disease",
       fill = "Condition") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for readability
# Convert ggplot to interactive plotly chart
interactive_disease_plot <- ggplotly(disease_plot)

# Print the interactive plot
interactive_disease_plot
# Calculate frequencies
condition_frequency <- combined_data %>%
  group_by(Parent_Company, condition)%>%
  filter(!is.na(Parent_Company)) %>%
  summarize(frequency = n(), .groups = 'drop')
condition_frequency

# Plot the frequency of diseases by process category
disease_plot <-ggplot(condition_frequency, aes(x = condition, y = frequency, fill = Parent_Company)) +
  geom_bar(stat = "identity", position = "stack") +  # 'stack' stacks the bars for different conditions
  labs(title = "Frequency of Diseases by parent company",
       x = "Process Category",
       y = "Frequency of Disease",
       fill = "Condition") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for readability
# Convert ggplot to interactive plotly chart
interactive_disease_plot_parent <- ggplotly(disease_plot)

# Print the interactive plot
interactive_disease_plot_parent
# Define the data
dog_data <- data.frame(
  Category = c("Died from Disease", "Survived or Died from Other Causes"),
  Count = c(832, 3044 - 832)
)

# Create the pie chart
pie_chart <- plot_ly(dog_data, labels = ~Category, values = ~Count, type = 'pie',
                     textinfo = 'label+percent',
                     insidetextorientation = 'radial') %>%
  layout(title = "Proportion of Dogs That Died from Disease")

# Print the pie chart
pie_chart
# Summarize data
death_summary <- death_data %>%
  dplyr::count(is_cause_of_death) %>%
  dplyr::mutate(Category = ifelse(is_cause_of_death == 1, "Died from Disease", "Did Not Die from Disease"))

# Rename columns for clarity
death_summary <- dplyr::rename(death_summary, Count = n)

# Create the pie chart
pie_chart_death_cause <- plot_ly(death_summary, labels = ~Category, values = ~Count, type = 'pie',
                     textinfo = 'label+percent',
                     insidetextorientation = 'radial') %>%
  layout(title = "Proportion of Dogs Dying from Disease")

# Print the pie chart
pie_chart_death_cause
save(interactive_disease_plot,pie_chart,pie_chart_death_cause,interactive_disease_plot_parent, file = "~/Dropbox (Edison_Lab@UGA)/Projects/vet/Deanna/Golden_Data/death2.RData")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMjIExvYWQgZGF0YQpgYGB7cn0KIyBSZXN0b3JlIHRoZSBvYmplY3QKRGlldF9EYXRhX0NsZWFuID0gcmVhZFJEUyhmaWxlID0gIn4vRHJvcGJveCAoRWRpc29uX0xhYkBVR0EpL1Byb2plY3RzL3ZldC9EZWFubmEvR29sZGVuX0RhdGEvQ2xlYW5EYXRhLnJkcyIpCmBgYAoKCiMjIEZyZXF1ZW5jeSBhdCB3aGljaCBwYXJ0aWNpcGFudHMgc3dpdGNoIGNhdGVnb3JpemF0aW9uCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1hcmtvdmNoYWluKQoKZGF0YSA8LSBEaWV0X0RhdGFfQ2xlYW5bb3JkZXIoRGlldF9EYXRhX0NsZWFuJGlkLCBEaWV0X0RhdGFfQ2xlYW4kY2FsZW5kYXJ5ZWFyKSxdCgogIyBDcmVhdGUgYSBsaXN0IG9mIGFsbCB1bmlxdWUgY2F0ZWdvcmllcwphbGxfY2F0ZWdvcmllcyA8LSB1bmlxdWUoZGF0YSRwcm9jZXNzLmNhdGVnb3J5KQoKIyBDcmVhdGluZyBzZXF1ZW5jZXMKZGF0YV9zZXF1ZW5jZSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGlkKSAlPiUKICBzdW1tYXJpc2UoQ2F0ZWdvcnlfU2VxdWVuY2UgPSBsaXN0KHByb2Nlc3MuY2F0ZWdvcnkpKSAlPiUKICB1bmdyb3VwKCkKCgojIEZ1bmN0aW9uIHRvIGZpdCBNYXJrb3YgY2hhaW4gYW5kIHJldHVybiBhIGNvbXBsZXRlIHRyYW5zaXRpb24gbWF0cml4CmdldF9jb21wbGV0ZV9tYXRyaXggPC0gZnVuY3Rpb24oc2VxdWVuY2UpIHsKICAjIEZpdCB0aGUgTWFya292IGNoYWluCiAgbWNGaXQgPC0gbWFya292Y2hhaW5GaXQoZGF0YSA9IHNlcXVlbmNlKSRlc3RpbWF0ZQogICMgQ3JlYXRlIGEgY29tcGxldGUgbWF0cml4IGluY2x1ZGluZyBhbGwgY2F0ZWdvcmllcwogIGNvbXBsZXRlX21hdHJpeCA8LSBtYXRyaXgoMCwgbGVuZ3RoKGFsbF9jYXRlZ29yaWVzKSwgbGVuZ3RoKGFsbF9jYXRlZ29yaWVzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbW5hbWVzID0gbGlzdChhbGxfY2F0ZWdvcmllcywgYWxsX2NhdGVnb3JpZXMpKQogIHRyYW5zaXRpb25zIDwtIG1jRml0QHRyYW5zaXRpb25NYXRyaXgKICAjIEZpbGwgdGhlIGNvbXBsZXRlIG1hdHJpeCB3aXRoIGV4aXN0aW5nIHRyYW5zaXRpb25zCiAgcm93bmFtZXNfdG9fdXNlIDwtIGludGVyc2VjdChyb3duYW1lcyh0cmFuc2l0aW9ucyksIGFsbF9jYXRlZ29yaWVzKQogIGNvbG5hbWVzX3RvX3VzZSA8LSBpbnRlcnNlY3QoY29sbmFtZXModHJhbnNpdGlvbnMpLCBhbGxfY2F0ZWdvcmllcykKICBjb21wbGV0ZV9tYXRyaXhbcm93bmFtZXNfdG9fdXNlLCBjb2xuYW1lc190b191c2VdIDwtIHRyYW5zaXRpb25zW3Jvd25hbWVzX3RvX3VzZSwgY29sbmFtZXNfdG9fdXNlXQogIHJldHVybihjb21wbGV0ZV9tYXRyaXgpCn0KCiMgQWRqdXN0IHRoZSBmdW5jdGlvbiB0byBjb252ZXJ0IHNlcXVlbmNlcyB0byB0cmFuc2l0aW9uIG1hdHJpeApnZXRfdHJhbnNpdGlvbl9tYXRyaXggPC0gZnVuY3Rpb24oc2VxdWVuY2VfbGlzdCkgewogIG1jTGlzdCA8LSBsYXBwbHkoc2VxdWVuY2VfbGlzdCwgZ2V0X2NvbXBsZXRlX21hdHJpeCkKICAKICAjIFN1bW1pbmcgYWxsIG1hdHJpY2VzCiAgbWF0cml4X3N1bSA8LSBSZWR1Y2UoIisiLCBtY0xpc3QpCiAgcmV0dXJuKG1hdHJpeF9zdW0gLyBsZW5ndGgobWNMaXN0KSkgICMgTm9ybWFsaXppbmcKfQoKIyBDcmVhdGluZyB0aGUgdHJhbnNpdGlvbiBtYXRyaXgKdHJhbnNpdGlvbl9tYXRyaXggPC0gZ2V0X3RyYW5zaXRpb25fbWF0cml4KGRhdGFfc2VxdWVuY2UkQ2F0ZWdvcnlfU2VxdWVuY2UpCnByaW50KHRyYW5zaXRpb25fbWF0cml4KQpgYGAKCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKdHJhbnNpdGlvbl9kZiA8LSBhcy5kYXRhLmZyYW1lKGFzLnRhYmxlKHRyYW5zaXRpb25fbWF0cml4KSkKY29sbmFtZXModHJhbnNpdGlvbl9kZikgPC0gYygiRnJvbSIsICJUbyIsICJGcmVxdWVuY3kiKQoKaGVhdG1hcDEgPSBnZ3Bsb3QodHJhbnNpdGlvbl9kZiwgYWVzKHggPSBGcm9tLCB5ID0gVG8sIGZpbGwgPSBGcmVxdWVuY3kpKSArCiAgZ2VvbV90aWxlKCkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiLCBtaWQgPSAid2hpdGUiLCBtaWRwb2ludCA9IDAuNSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJUcmFuc2l0aW9uIEhlYXRtYXAiLCB4ID0gIkZyb20gQ2F0ZWdvcnkiLCB5ID0gIlRvIENhdGVnb3J5IiwgZmlsbCA9ICJUcmFuc2l0aW9uIEZyZXF1ZW5jeSIpCgpgYGAKCmltcGxpZXMgYSBzaWduaWZpY2FudCB0ZW5kZW5jeSBmb3Igc3ViamVjdHMgdG8gcmVtYWluIGluIHRoZSBsYXN0IGNhdGVnb3J5IGxpc3RlZC4gVGhpcyBjYW4gaW5kaWNhdGUgdGhhdCBvbmNlIHN1YmplY3RzIGVudGVyIHRoaXMgY2F0ZWdvcnksIHRoZXkgYXJlIGxpa2VseSB0byBzdGF5IHRoZXJlLCBzdWdnZXN0aW5nIHN0YWJpbGl0eSBvciBhIHRlcm1pbmFsIHN0YWdlIGRlcGVuZGluZyBvbiB0aGUgY29udGV4dCBvZiB0aGUgc3R1ZHkuCgoKYGBge3J9CiMgCmRhdGEkWWVhciA8LSBhcy5pbnRlZ2VyKGRhdGEkY2FsZW5kYXJ5ZWFyKQoKIyBDYWxjdWxhdGUgdGhlIGR1cmF0aW9uIG9mIHN0YXkgaW4gZWFjaCBjYXRlZ29yeSBmb3IgZWFjaCBzdWJqZWN0CmR1cmF0aW9ucyA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGlkLCBwcm9jZXNzLmNhdGVnb3J5KSAlPiUKICBzdW1tYXJpc2UoCiAgICBTdGFydF9ZZWFyID0gbWluKFllYXIpLAogICAgRW5kX1llYXIgPSBtYXgoWWVhciksCiAgICBEdXJhdGlvbiA9IEVuZF9ZZWFyIC0gU3RhcnRfWWVhciArIDEgICMgKzEgYmVjYXVzZSBpZiBzdGFydCBhbmQgZW5kIHllYXIgYXJlIHRoZSBzYW1lLCBkdXJhdGlvbiBpcyAxIHllYXIKICApICU+JQogIHVuZ3JvdXAoKQoKIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZHVyYXRpb25zIGRhdGEgZnJhbWUKaGVhZChkdXJhdGlvbnMpCgojIENhbGN1bGF0ZSB0aGUgYXZlcmFnZSBkdXJhdGlvbiBvZiBzdGF5IHBlciBjYXRlZ29yeQphdmVyYWdlX2R1cmF0aW9ucyA8LSBkdXJhdGlvbnMgJT4lCiAgZ3JvdXBfYnkocHJvY2Vzcy5jYXRlZ29yeSkgJT4lCiAgc3VtbWFyaXNlKEF2ZXJhZ2VfRHVyYXRpb24gPSBtZWFuKER1cmF0aW9uKSkKCiMgVmlldyB0aGUgYXZlcmFnZSBkdXJhdGlvbnMKaGVhZChhdmVyYWdlX2R1cmF0aW9ucykKCgpkdXJhdGlvbnNfZGF0YXRhYmxlID0gZGF0YXRhYmxlKGR1cmF0aW9ucywgb3B0aW9ucyA9IGxpc3QoKSwgY2xhc3MgPSAiZGlzcGxheSIpCmR1cmF0aW9uc19kYXRhdGFibGUKCmF2ZXJhZ2VfZHVyYXRpb25zX2RhdGF0YWJsZSA9IGRhdGF0YWJsZShhdmVyYWdlX2R1cmF0aW9ucywgb3B0aW9ucyA9IGxpc3QoKSwgY2xhc3MgPSAiZGlzcGxheSIpCmF2ZXJhZ2VfZHVyYXRpb25zX2RhdGF0YWJsZQpgYGAKYGBge3J9CiMgQWRkaW5nIGEgc21hbGwgY29uc3RhbnQgdG8gaGFuZGxlIHplcm9zCmsgPSAwLjAwMQp0cmFuc2l0aW9uX2RmJEZyZXFfQWRqdXN0ZWQgPSB0cmFuc2l0aW9uX2RmJEZyZXEgKyBrCiMgQXBwbHlpbmcgYSBsb2cgdHJhbnNmb3JtYXRpb24gKGJhc2UgMTApCnRyYW5zaXRpb25fZGYkTG9nX0ZyZXF1ZW5jeSA9IGxvZzEwKHRyYW5zaXRpb25fZGYkRnJlcV9BZGp1c3RlZCkKYGBgCgpgYGB7cn0KIyBDb252ZXJ0aW5nIG1hdHJpeCB0byBkYXRhIGZyYW1lIGZvciBwbG90dGluZwojdHJhbnNpdGlvbl9kZiA8LSBhcy5kYXRhLmZyYW1lKGFzLnRhYmxlKHRyYW5zaXRpb25fbWF0cml4KSkKCiMgQ3JlYXRlIGludGVyYWN0aXZlIGhlYXRtYXAKaGVhdG1hcDIgPSBwbG90X2x5KGRhdGEgPSB0cmFuc2l0aW9uX2RmLCB4ID0gfkZyb20sIHkgPSB+VG8sIHogPSB+TG9nX0ZyZXF1ZW5jeSwgdHlwZSA9ICJoZWF0bWFwIiwgY29sb3JzID0gY29sb3JSYW1wKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpLAogICAgICAgIHRleHQgPSB+cGFzdGUoIlRyYW5zaXRpb24gZnJvbSIsIEZyb20sICJ0byIsIFRvLCAiPGJyPlByb2JhYmlsaXR5OiIsIEZyZXF1ZW5jeSksCiAgICAgICAgaG92ZXJpbmZvID0gInRleHQiKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiVHJhbnNpdGlvbiBNYXRyaXggSGVhdG1hcCIsCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJGcm9tIENhdGVnb3J5IiksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJUbyBDYXRlZ29yeSIsIGF1dG9yYW5nZSA9ICJyZXZlcnNlZCIpKSAgIyBSZXZlcnNpbmcgeS1heGlzIHRvIG1hdGNoIGhlYXRtYXAgY29udmVudGlvbnMKaGVhdG1hcDIKYGBgCgojIyBGcmVxdWVuY3kgZm9yIHN3aXRjaGluZyBkaWV0IGNvbXBhbmllcwoKYGBge3J9CgogIyBDcmVhdGUgYSBsaXN0IG9mIGFsbCB1bmlxdWUgY2F0ZWdvcmllcwphbGxfY2F0ZWdvcmllcyA8LSB1bmlxdWUoZGF0YSRQYXJlbnRfQ29tcGFueSkKCiMgRnVuY3Rpb24gdG8gZml0IE1hcmtvdiBjaGFpbiBhbmQgcmV0dXJuIGEgY29tcGxldGUgdHJhbnNpdGlvbiBtYXRyaXgKZ2V0X2NvbXBsZXRlX21hdHJpeCA8LSBmdW5jdGlvbihzZXF1ZW5jZSkgewogICMgRml0IHRoZSBNYXJrb3YgY2hhaW4KICBtY0ZpdCA8LSBtYXJrb3ZjaGFpbkZpdChkYXRhID0gc2VxdWVuY2UpJGVzdGltYXRlCiAgIyBDcmVhdGUgYSBjb21wbGV0ZSBtYXRyaXggaW5jbHVkaW5nIGFsbCBjYXRlZ29yaWVzCiAgY29tcGxldGVfbWF0cml4IDwtIG1hdHJpeCgwLCBsZW5ndGgoYWxsX2NhdGVnb3JpZXMpLCBsZW5ndGgoYWxsX2NhdGVnb3JpZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltbmFtZXMgPSBsaXN0KGFsbF9jYXRlZ29yaWVzLCBhbGxfY2F0ZWdvcmllcykpCiAgdHJhbnNpdGlvbnMgPC0gbWNGaXRAdHJhbnNpdGlvbk1hdHJpeAogICMgRmlsbCB0aGUgY29tcGxldGUgbWF0cml4IHdpdGggZXhpc3RpbmcgdHJhbnNpdGlvbnMKICByb3duYW1lc190b191c2UgPC0gaW50ZXJzZWN0KHJvd25hbWVzKHRyYW5zaXRpb25zKSwgYWxsX2NhdGVnb3JpZXMpCiAgY29sbmFtZXNfdG9fdXNlIDwtIGludGVyc2VjdChjb2xuYW1lcyh0cmFuc2l0aW9ucyksIGFsbF9jYXRlZ29yaWVzKQogIGNvbXBsZXRlX21hdHJpeFtyb3duYW1lc190b191c2UsIGNvbG5hbWVzX3RvX3VzZV0gPC0gdHJhbnNpdGlvbnNbcm93bmFtZXNfdG9fdXNlLCBjb2xuYW1lc190b191c2VdCiAgcmV0dXJuKGNvbXBsZXRlX21hdHJpeCkKfQoKIyBBZGp1c3QgdGhlIGZ1bmN0aW9uIHRvIGNvbnZlcnQgc2VxdWVuY2VzIHRvIHRyYW5zaXRpb24gbWF0cml4CmdldF90cmFuc2l0aW9uX21hdHJpeCA8LSBmdW5jdGlvbihzZXF1ZW5jZV9saXN0KSB7CiAgbWNMaXN0IDwtIGxhcHBseShzZXF1ZW5jZV9saXN0LCBnZXRfY29tcGxldGVfbWF0cml4KQogIAogICMgU3VtbWluZyBhbGwgbWF0cmljZXMKICBtYXRyaXhfc3VtIDwtIFJlZHVjZSgiKyIsIG1jTGlzdCkKICByZXR1cm4obWF0cml4X3N1bSAvIGxlbmd0aChtY0xpc3QpKSAgIyBOb3JtYWxpemluZwp9CgojIENyZWF0aW5nIHRoZSB0cmFuc2l0aW9uIG1hdHJpeAp0cmFuc2l0aW9uX21hdHJpeCA8LSBnZXRfdHJhbnNpdGlvbl9tYXRyaXgoZGF0YV9zZXF1ZW5jZSRDYXRlZ29yeV9TZXF1ZW5jZSkKCmBgYAoKCmBgYHtyfQojIApkYXRhJFllYXIgPC0gYXMuaW50ZWdlcihkYXRhJGNhbGVuZGFyeWVhcikKCiMgQ2FsY3VsYXRlIHRoZSBkdXJhdGlvbiBvZiBzdGF5IGluIGVhY2ggY2F0ZWdvcnkgZm9yIGVhY2ggc3ViamVjdApkdXJhdGlvbnMgPC0gZGF0YSAlPiUKICBncm91cF9ieShpZCwgUGFyZW50X0NvbXBhbnkpICU+JQogIHN1bW1hcmlzZSgKICAgIFN0YXJ0X1llYXIgPSBtaW4oWWVhciksCiAgICBFbmRfWWVhciA9IG1heChZZWFyKSwKICAgIER1cmF0aW9uID0gRW5kX1llYXIgLSBTdGFydF9ZZWFyICsgMSAgIyArMSBiZWNhdXNlIGlmIHN0YXJ0IGFuZCBlbmQgeWVhciBhcmUgdGhlIHNhbWUsIGR1cmF0aW9uIGlzIDEgeWVhcgogICkgJT4lCiAgdW5ncm91cCgpCgojIFZpZXcgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkdXJhdGlvbnMgZGF0YSBmcmFtZQpoZWFkKGR1cmF0aW9ucykKCiMgQ2FsY3VsYXRlIHRoZSBhdmVyYWdlIGR1cmF0aW9uIG9mIHN0YXkgcGVyIGNhdGVnb3J5CmF2ZXJhZ2VfZHVyYXRpb25zIDwtIGR1cmF0aW9ucyAlPiUKICBncm91cF9ieShQYXJlbnRfQ29tcGFueSkgJT4lCiAgc3VtbWFyaXNlKEF2ZXJhZ2VfRHVyYXRpb24gPSBtZWFuKER1cmF0aW9uKSkKCiMgVmlldyB0aGUgYXZlcmFnZSBkdXJhdGlvbnMKaGVhZChhdmVyYWdlX2R1cmF0aW9ucykKCgpkdXJhdGlvbnNfZGF0YXRhYmxlMiA9IGRhdGF0YWJsZShkdXJhdGlvbnMsIG9wdGlvbnMgPSBsaXN0KCksIGNsYXNzID0gImRpc3BsYXkiKQpkdXJhdGlvbnNfZGF0YXRhYmxlCgphdmVyYWdlX2R1cmF0aW9uc19kYXRhdGFibGUyID0gZGF0YXRhYmxlKGF2ZXJhZ2VfZHVyYXRpb25zLCBvcHRpb25zID0gbGlzdCgpLCBjbGFzcyA9ICJkaXNwbGF5IikKYXZlcmFnZV9kdXJhdGlvbnNfZGF0YXRhYmxlCmBgYAojIyBGcmVxdWVuY3kgZm9yIHN3aXRjaGluZyBkaWV0IGJyYW5kcwoKYGBge3J9CgogIyBDcmVhdGUgYSBsaXN0IG9mIGFsbCB1bmlxdWUgY2F0ZWdvcmllcwphbGxfY2F0ZWdvcmllcyA8LSB1bmlxdWUoZGF0YSRCcmFuZF9Db21wYW55KQoKIyBGdW5jdGlvbiB0byBmaXQgTWFya292IGNoYWluIGFuZCByZXR1cm4gYSBjb21wbGV0ZSB0cmFuc2l0aW9uIG1hdHJpeApnZXRfY29tcGxldGVfbWF0cml4IDwtIGZ1bmN0aW9uKHNlcXVlbmNlKSB7CiAgIyBGaXQgdGhlIE1hcmtvdiBjaGFpbgogIG1jRml0IDwtIG1hcmtvdmNoYWluRml0KGRhdGEgPSBzZXF1ZW5jZSkkZXN0aW1hdGUKICAjIENyZWF0ZSBhIGNvbXBsZXRlIG1hdHJpeCBpbmNsdWRpbmcgYWxsIGNhdGVnb3JpZXMKICBjb21wbGV0ZV9tYXRyaXggPC0gbWF0cml4KDAsIGxlbmd0aChhbGxfY2F0ZWdvcmllcyksIGxlbmd0aChhbGxfY2F0ZWdvcmllcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1uYW1lcyA9IGxpc3QoYWxsX2NhdGVnb3JpZXMsIGFsbF9jYXRlZ29yaWVzKSkKICB0cmFuc2l0aW9ucyA8LSBtY0ZpdEB0cmFuc2l0aW9uTWF0cml4CiAgIyBGaWxsIHRoZSBjb21wbGV0ZSBtYXRyaXggd2l0aCBleGlzdGluZyB0cmFuc2l0aW9ucwogIHJvd25hbWVzX3RvX3VzZSA8LSBpbnRlcnNlY3Qocm93bmFtZXModHJhbnNpdGlvbnMpLCBhbGxfY2F0ZWdvcmllcykKICBjb2xuYW1lc190b191c2UgPC0gaW50ZXJzZWN0KGNvbG5hbWVzKHRyYW5zaXRpb25zKSwgYWxsX2NhdGVnb3JpZXMpCiAgY29tcGxldGVfbWF0cml4W3Jvd25hbWVzX3RvX3VzZSwgY29sbmFtZXNfdG9fdXNlXSA8LSB0cmFuc2l0aW9uc1tyb3duYW1lc190b191c2UsIGNvbG5hbWVzX3RvX3VzZV0KICByZXR1cm4oY29tcGxldGVfbWF0cml4KQp9CgojIEFkanVzdCB0aGUgZnVuY3Rpb24gdG8gY29udmVydCBzZXF1ZW5jZXMgdG8gdHJhbnNpdGlvbiBtYXRyaXgKZ2V0X3RyYW5zaXRpb25fbWF0cml4IDwtIGZ1bmN0aW9uKHNlcXVlbmNlX2xpc3QpIHsKICBtY0xpc3QgPC0gbGFwcGx5KHNlcXVlbmNlX2xpc3QsIGdldF9jb21wbGV0ZV9tYXRyaXgpCiAgCiAgIyBTdW1taW5nIGFsbCBtYXRyaWNlcwogIG1hdHJpeF9zdW0gPC0gUmVkdWNlKCIrIiwgbWNMaXN0KQogIHJldHVybihtYXRyaXhfc3VtIC8gbGVuZ3RoKG1jTGlzdCkpICAjIE5vcm1hbGl6aW5nCn0KCiMgQ3JlYXRpbmcgdGhlIHRyYW5zaXRpb24gbWF0cml4CnRyYW5zaXRpb25fbWF0cml4IDwtIGdldF90cmFuc2l0aW9uX21hdHJpeChkYXRhX3NlcXVlbmNlJENhdGVnb3J5X1NlcXVlbmNlKQoKYGBgCgoKYGBge3J9CiMgCmRhdGEkWWVhciA8LSBhcy5pbnRlZ2VyKGRhdGEkY2FsZW5kYXJ5ZWFyKQoKIyBDYWxjdWxhdGUgdGhlIGR1cmF0aW9uIG9mIHN0YXkgaW4gZWFjaCBjYXRlZ29yeSBmb3IgZWFjaCBzdWJqZWN0CmR1cmF0aW9ucyA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGlkLCBCcmFuZF9Db21wYW55KSAlPiUKICBzdW1tYXJpc2UoCiAgICBTdGFydF9ZZWFyID0gbWluKFllYXIpLAogICAgRW5kX1llYXIgPSBtYXgoWWVhciksCiAgICBEdXJhdGlvbiA9IEVuZF9ZZWFyIC0gU3RhcnRfWWVhciArIDEgICMgKzEgYmVjYXVzZSBpZiBzdGFydCBhbmQgZW5kIHllYXIgYXJlIHRoZSBzYW1lLCBkdXJhdGlvbiBpcyAxIHllYXIKICApICU+JQogIHVuZ3JvdXAoKQoKIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZHVyYXRpb25zIGRhdGEgZnJhbWUKaGVhZChkdXJhdGlvbnMpCgojIENhbGN1bGF0ZSB0aGUgYXZlcmFnZSBkdXJhdGlvbiBvZiBzdGF5IHBlciBjYXRlZ29yeQphdmVyYWdlX2R1cmF0aW9ucyA8LSBkdXJhdGlvbnMgJT4lCiAgZ3JvdXBfYnkoQnJhbmRfQ29tcGFueSkgJT4lCiAgc3VtbWFyaXNlKEF2ZXJhZ2VfRHVyYXRpb24gPSBtZWFuKER1cmF0aW9uKSkKCiMgVmlldyB0aGUgYXZlcmFnZSBkdXJhdGlvbnMKaGVhZChhdmVyYWdlX2R1cmF0aW9ucykKCgpkdXJhdGlvbnNfZGF0YXRhYmxlMyA9IGRhdGF0YWJsZShkdXJhdGlvbnMsIG9wdGlvbnMgPSBsaXN0KCksIGNsYXNzID0gImRpc3BsYXkiKQpkdXJhdGlvbnNfZGF0YXRhYmxlMwoKYXZlcmFnZV9kdXJhdGlvbnNfZGF0YXRhYmxlMyA9IGRhdGF0YWJsZShhdmVyYWdlX2R1cmF0aW9ucywgb3B0aW9ucyA9IGxpc3QoKSwgY2xhc3MgPSAiZGlzcGxheSIpCmF2ZXJhZ2VfZHVyYXRpb25zX2RhdGF0YWJsZTMKYGBgCgoKYGBge3J9CnNhdmUoaGVhdG1hcDIsIGZpbGUgPSAifi9Ecm9wYm94IChFZGlzb25fTGFiQFVHQSkvUHJvamVjdHMvdmV0L0RlYW5uYS9Hb2xkZW5fRGF0YS9maWd1cmVzX3RyZW5kcy5SRGF0YSIpCgpzYXZlKGF2ZXJhZ2VfZHVyYXRpb25zX2RhdGF0YWJsZSxkdXJhdGlvbnNfZGF0YXRhYmxlLGR1cmF0aW9uc19kYXRhdGFibGUyLGF2ZXJhZ2VfZHVyYXRpb25zX2RhdGF0YWJsZTIsYXZlcmFnZV9kdXJhdGlvbnNfZGF0YXRhYmxlMyxkdXJhdGlvbnNfZGF0YXRhYmxlMywgZmlsZSA9ICJ+L0Ryb3Bib3ggKEVkaXNvbl9MYWJAVUdBKS9Qcm9qZWN0cy92ZXQvRGVhbm5hL0dvbGRlbl9EYXRhL3RhYmxlc190cmVuZHMuUkRhdGEiKQoKCmBgYAoKIyBEZWF0aCBkYXRhIGFuZCBkaWV0IGRhdGEKCmBgYHtyfQojIE1lcmdlIHRoZSBkYXRhc2V0cwpjb21iaW5lZF9kYXRhIDwtIGxlZnRfam9pbihkZWF0aF9kYXRhLCBEaWV0X0RhdGFfQ2xlYW4sIGJ5ID0gYygiaWQiLCAic3R1ZHlfeWVhciIpKQoKYGBgCgpgYGB7cn0KIyBMb2dpc3RpYyByZWdyZXNzaW9uIHRvIHNlZSBpZiBkaWV0IHByZWRpY3RzIGRpc2Vhc2Ugb2NjdXJyZW5jZQptb2RlbF9kaXNlYXNlIDwtIGdsbShjb25kaXRpb24gIT0gIk5vIERpc2Vhc2UiIH4gQkNTICsgQnJhbmRfQ29tcGFueSArIFBhcmVudF9Db21wYW55ICsgcHJvY2Vzcy5jYXRlZ29yeSArIHByb2Nlc3Muc3VidHlwZSwgCiAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb21iaW5lZF9kYXRhLCBmYW1pbHkgPSAiYmlub21pYWwiKQoKIyBMb2dpc3RpYyByZWdyZXNzaW9uIHRvIHNlZSBpZiBkaWV0IHByZWRpY3RzIGRlYXRoIGNhdXNlZCBieSBkaXNlYXNlCm1vZGVsX2RlYXRoIDwtIGdsbShjb25kaXRpb24gIT0gIk5vIERpc2Vhc2UiICYgaXNfY2F1c2Vfb2ZfZGVhdGggPT0gMSB+IEJDUyArIEJyYW5kX0NvbXBhbnkgKyBQYXJlbnRfQ29tcGFueSArIHByb2Nlc3MuY2F0ZWdvcnkgKyBwcm9jZXNzLnN1YnR5cGUsIAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbWJpbmVkX2RhdGEsIGZhbWlseSA9ICJiaW5vbWlhbCIpCgojIFN1bW1hcml6ZSB0aGUgbW9kZWwKc3VtbWFyeShtb2RlbF9kaXNlYXNlKQpzdW1tYXJ5KG1vZGVsX2RlYXRoKQoKCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIGZyZXF1ZW5jaWVzCmNvbmRpdGlvbl9mcmVxdWVuY3kgPC0gY29tYmluZWRfZGF0YSAlPiUKICBncm91cF9ieShwcm9jZXNzLmNhdGVnb3J5LCBjb25kaXRpb24pJT4lCiAgZmlsdGVyKCFpcy5uYShwcm9jZXNzLmNhdGVnb3J5KSkgJT4lCiAgc3VtbWFyaXplKGZyZXF1ZW5jeSA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykKY29uZGl0aW9uX2ZyZXF1ZW5jeQoKIyBQbG90IHRoZSBmcmVxdWVuY3kgb2YgZGlzZWFzZXMgYnkgcHJvY2VzcyBjYXRlZ29yeQpkaXNlYXNlX3Bsb3QgPC1nZ3Bsb3QoY29uZGl0aW9uX2ZyZXF1ZW5jeSwgYWVzKHggPSBjb25kaXRpb24sIHkgPSBmcmVxdWVuY3ksIGZpbGwgPSBwcm9jZXNzLmNhdGVnb3J5KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsgICMgJ3N0YWNrJyBzdGFja3MgdGhlIGJhcnMgZm9yIGRpZmZlcmVudCBjb25kaXRpb25zCiAgbGFicyh0aXRsZSA9ICJGcmVxdWVuY3kgb2YgRGlzZWFzZXMgYnkgUHJvY2VzcyBDYXRlZ29yeSIsCiAgICAgICB4ID0gIlByb2Nlc3MgQ2F0ZWdvcnkiLAogICAgICAgeSA9ICJGcmVxdWVuY3kgb2YgRGlzZWFzZSIsCiAgICAgICBmaWxsID0gIkNvbmRpdGlvbiIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKYGBge3J9CiMgQ29udmVydCBnZ3Bsb3QgdG8gaW50ZXJhY3RpdmUgcGxvdGx5IGNoYXJ0CmludGVyYWN0aXZlX2Rpc2Vhc2VfcGxvdCA8LSBnZ3Bsb3RseShkaXNlYXNlX3Bsb3QpCgojIFByaW50IHRoZSBpbnRlcmFjdGl2ZSBwbG90CmludGVyYWN0aXZlX2Rpc2Vhc2VfcGxvdApgYGAKCmBgYHtyfQojIENhbGN1bGF0ZSBmcmVxdWVuY2llcwpjb25kaXRpb25fZnJlcXVlbmN5IDwtIGNvbWJpbmVkX2RhdGEgJT4lCiAgZ3JvdXBfYnkoUGFyZW50X0NvbXBhbnksIGNvbmRpdGlvbiklPiUKICBmaWx0ZXIoIWlzLm5hKFBhcmVudF9Db21wYW55KSkgJT4lCiAgc3VtbWFyaXplKGZyZXF1ZW5jeSA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykKY29uZGl0aW9uX2ZyZXF1ZW5jeQoKIyBQbG90IHRoZSBmcmVxdWVuY3kgb2YgZGlzZWFzZXMgYnkgcHJvY2VzcyBjYXRlZ29yeQpkaXNlYXNlX3Bsb3QgPC1nZ3Bsb3QoY29uZGl0aW9uX2ZyZXF1ZW5jeSwgYWVzKHggPSBjb25kaXRpb24sIHkgPSBmcmVxdWVuY3ksIGZpbGwgPSBQYXJlbnRfQ29tcGFueSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAic3RhY2siKSArICAjICdzdGFjaycgc3RhY2tzIHRoZSBiYXJzIGZvciBkaWZmZXJlbnQgY29uZGl0aW9ucwogIGxhYnModGl0bGUgPSAiRnJlcXVlbmN5IG9mIERpc2Vhc2VzIGJ5IHBhcmVudCBjb21wYW55IiwKICAgICAgIHggPSAiUHJvY2VzcyBDYXRlZ29yeSIsCiAgICAgICB5ID0gIkZyZXF1ZW5jeSBvZiBEaXNlYXNlIiwKICAgICAgIGZpbGwgPSAiQ29uZGl0aW9uIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYAoKYGBge3J9CiMgQ29udmVydCBnZ3Bsb3QgdG8gaW50ZXJhY3RpdmUgcGxvdGx5IGNoYXJ0CmludGVyYWN0aXZlX2Rpc2Vhc2VfcGxvdF9wYXJlbnQgPC0gZ2dwbG90bHkoZGlzZWFzZV9wbG90KQoKIyBQcmludCB0aGUgaW50ZXJhY3RpdmUgcGxvdAppbnRlcmFjdGl2ZV9kaXNlYXNlX3Bsb3RfcGFyZW50CmBgYAoKYGBge3J9CiMgRGVmaW5lIHRoZSBkYXRhCmRvZ19kYXRhIDwtIGRhdGEuZnJhbWUoCiAgQ2F0ZWdvcnkgPSBjKCJEaWVkIGZyb20gRGlzZWFzZSIsICJTdXJ2aXZlZCBvciBEaWVkIGZyb20gT3RoZXIgQ2F1c2VzIiksCiAgQ291bnQgPSBjKDgzMiwgMzA0NCAtIDgzMikKKQoKIyBDcmVhdGUgdGhlIHBpZSBjaGFydApwaWVfY2hhcnQgPC0gcGxvdF9seShkb2dfZGF0YSwgbGFiZWxzID0gfkNhdGVnb3J5LCB2YWx1ZXMgPSB+Q291bnQsIHR5cGUgPSAncGllJywKICAgICAgICAgICAgICAgICAgICAgdGV4dGluZm8gPSAnbGFiZWwrcGVyY2VudCcsCiAgICAgICAgICAgICAgICAgICAgIGluc2lkZXRleHRvcmllbnRhdGlvbiA9ICdyYWRpYWwnKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiUHJvcG9ydGlvbiBvZiBEb2dzIFRoYXQgRGllZCBmcm9tIERpc2Vhc2UiKQoKIyBQcmludCB0aGUgcGllIGNoYXJ0CnBpZV9jaGFydApgYGAKCgpgYGB7cn0KIyBTdW1tYXJpemUgZGF0YQpkZWF0aF9zdW1tYXJ5IDwtIGRlYXRoX2RhdGEgJT4lCiAgZHBseXI6OmNvdW50KGlzX2NhdXNlX29mX2RlYXRoKSAlPiUKICBkcGx5cjo6bXV0YXRlKENhdGVnb3J5ID0gaWZlbHNlKGlzX2NhdXNlX29mX2RlYXRoID09IDEsICJEaWVkIGZyb20gRGlzZWFzZSIsICJEaWQgTm90IERpZSBmcm9tIERpc2Vhc2UiKSkKCiMgUmVuYW1lIGNvbHVtbnMgZm9yIGNsYXJpdHkKZGVhdGhfc3VtbWFyeSA8LSBkcGx5cjo6cmVuYW1lKGRlYXRoX3N1bW1hcnksIENvdW50ID0gbikKCiMgQ3JlYXRlIHRoZSBwaWUgY2hhcnQKcGllX2NoYXJ0X2RlYXRoX2NhdXNlIDwtIHBsb3RfbHkoZGVhdGhfc3VtbWFyeSwgbGFiZWxzID0gfkNhdGVnb3J5LCB2YWx1ZXMgPSB+Q291bnQsIHR5cGUgPSAncGllJywKICAgICAgICAgICAgICAgICAgICAgdGV4dGluZm8gPSAnbGFiZWwrcGVyY2VudCcsCiAgICAgICAgICAgICAgICAgICAgIGluc2lkZXRleHRvcmllbnRhdGlvbiA9ICdyYWRpYWwnKSAlPiUKICBsYXlvdXQodGl0bGUgPSAiUHJvcG9ydGlvbiBvZiBEb2dzIER5aW5nIGZyb20gRGlzZWFzZSIpCgojIFByaW50IHRoZSBwaWUgY2hhcnQKcGllX2NoYXJ0X2RlYXRoX2NhdXNlCmBgYAoKYGBge3J9CnNhdmUoaW50ZXJhY3RpdmVfZGlzZWFzZV9wbG90LHBpZV9jaGFydCxwaWVfY2hhcnRfZGVhdGhfY2F1c2UsaW50ZXJhY3RpdmVfZGlzZWFzZV9wbG90X3BhcmVudCwgZmlsZSA9ICJ+L0Ryb3Bib3ggKEVkaXNvbl9MYWJAVUdBKS9Qcm9qZWN0cy92ZXQvRGVhbm5hL0dvbGRlbl9EYXRhL2RlYXRoMi5SRGF0YSIpCmBgYAoK